/********************************************************************************
* @file    extend_16ch.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-04-07
* @brief   16位恒流驱动芯片 MBI5020 JXI5020GP

对于ARM_M平台 @16M
1个NOP：(1/24000000)*1000*1000*1000==41.67ns
__NOP(); __NOP(); __NOP(); __NOP(); __NOP();      \
对于n76e003平台 @16M
1个nop      占用87ns
while(1)    占用194ns
函数调用     占用570ns

********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

/* Private Includes ----------------------------------------------------------*/
#include "extend_16ch.h"
#include "bsp_gpio.h"
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
/* Private Typedef -----------------------------------------------------------*/
/* Private Macro -------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
#include "bsp_pwm.h"

/* Private Function Prototypes -----------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
/**
 * @brief  器件硬件初始化
 * @param  *io: 引脚配置
 */
void extend_16ch_init(extend_16ch_t *io) {
    io_set_out_mode(io->clk, IO_OUT_PP);
    io_out(io->clk, IO_LOW);
    io_set_out_mode(io->sdi, IO_OUT_PP);
    io_out(io->sdi, IO_LOW);
    io_set_out_mode(io->le, IO_OUT_PP);
    io_out(io->le, IO_LOW);
    if (g_io_cfg[io->oe].type < IO_TYPE_TIM1_CH1 && g_io_cfg[io->oe].type > IO_TYPE_TIM2_CH4) {
        io_set_out_mode(io->oe, IO_OUT_PP);
        io_out(io->oe, IO_HIGH);
    } else {
    }
}

/**
 * @brief  注销器件引脚
 * @param  *io: 引脚配置
 */
void extend_16ch_deinit(extend_16ch_t *io) {
    io_deinit(io->clk);
    io_deinit(io->sdi);
    io_deinit(io->le);
    if (g_io_cfg[io->oe].type < IO_TYPE_TIM1_CH1 && g_io_cfg[io->oe].type > IO_TYPE_TIM2_CH4) {
        io_deinit(io->oe);
    } else {
    }
}

/**
 * @brief  写入数据
 * @param  *io: 引脚配置
 * @param  data[]: IO数据，请以倒叙传入。如U5,U4,U3,U2,U1。
 * @param  num: 器件数量
 */
void extend_16ch_write(extend_16ch_t *io, uint16_t data[], uint8_t num) {
    uint16_t temp = 0;
    uint8_t bit_val = 0;
    // 先关闭器件
    io_out(io->clk, IO_LOW);
    io_out(io->sdi, IO_LOW);
    io_out(io->le, IO_LOW);
    for (uint8_t i = 0; i < num; i++) {
        temp = data[i];
        for (uint8_t bit = 0; bit < 16; bit++) {
            bit_val = temp & 0x8000 ? 1 : 0;
            temp <<= 1;
            if (bit_val)
                io_out(io->sdi, IO_HIGH);
            else
                io_out(io->sdi, IO_LOW);
            io_out(io->clk, IO_HIGH);
            __NOP(); __NOP();
            io_out(io->clk, IO_LOW);
        }
    }
    io_out(io->le, IO_HIGH);
    __NOP(); __NOP();
    io_out(io->le, IO_LOW);
}

/**
 * @brief 器件使能脚--打开
 * @param io 引脚配置
 */
void extend_16ch_open(extend_16ch_t *io) {
    if (g_io_cfg[io->oe].type == IO_TYPE_OUT_PP) {
        io_out(io->oe, io->valid_level);
    } else { // 非输出脚，则为PWM模式
        if (io->valid_level)
            bsp_pwm_set_pulse(io->oe, io->intensity_ctrl);
        else
            bsp_pwm_set_pulse(io->oe, bsp_pwm_get_max_period(io->oe) - io->intensity_ctrl);
    }
}

/**
 * @brief 器件使能脚--关闭
 * @param io 引脚配置
 */
void extend_16ch_close(extend_16ch_t *io) {
    if (g_io_cfg[io->oe].type == IO_TYPE_OUT_PP) {
        io_out(io->oe, !(io->valid_level));
    } else {
        if (io->valid_level)
            bsp_pwm_set_pulse(io->oe, 0);
        else
            bsp_pwm_set_pulse(io->oe, -1);
    }
}
